﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using PMatch.Formats.Conversion;

namespace fconvert
{
	class Program
	{
		static void Main(string[] args)
		{
			ConversionSettings settings;
			ParseArguments(args, out settings);
			try
			{
				Console.WriteLine("Input: {0}", Path.GetFullPath(settings.InputFile));
				Console.WriteLine("Output: {0}", Path.GetFullPath(settings.OutputPath));
				var r = UniProtToSPMatchConverter.ConvertFile(settings);
				foreach (var item in r)
				{
					if (item.Mismatch) Console.WriteLine("{0} {1}", item.Sequence.accession, item.Mismatch ? "found mismatch" : "");
				}
				Console.WriteLine("{0} entries processed", r.Count());
			}
			catch (Exception ex)
			{
				Console.Error.WriteLine("Error converting file " + settings.InputFile + " to " + settings.OutputPath);
				var eex = ex;
				do
				{
					Console.Error.WriteLine(ex.Message + "\n");
				} while ((eex = eex.InnerException) != null);
			}
		}

		/// <summary>
		/// Construye la estructura de datos para ejecutar lo que desea el usuario
		/// </summary>
		private static void ParseArguments(string[] args, out ConversionSettings settings)
		{
			if (args.Length < 2 || args.Length > 6)
			{
				ShowUsage();
				Environment.Exit(255);
			}
			var tags = args.Skip(2).Take(4);
			settings = new ConversionSettings();
			settings.InputFile = args[0];
			settings.OutputPath = args[1];

			const string MODE_PARAM = "--mode=";
			const string MINCHAINS_PARAM = "--minchains=";
			const string MAXCHAINS_PARAM = "--maxchains=";

			// opciones de modo
			const string CHAINSONLY_OPT = "chainsonly";
			const string SITESONLY_OPT = "sitesonly";
			const string CHAINS_OPT = "chains";
			const string SITES_OPT = "sites";
			const string SKIP_OPT = "skip";

			foreach (var tag in tags)
			{
				if (tag.StartsWith(MODE_PARAM))
				{
					var mode = tag.Substring(MODE_PARAM.Length);
					if (mode == SKIP_OPT) settings.Mode = ConversionMode.SkipOnMismatch;
					else if (mode == CHAINSONLY_OPT) settings.Mode = ConversionMode.TakeChainsOnly;
					else if (mode == SITESONLY_OPT) settings.Mode = ConversionMode.TakeSitesOnly;
					else if (mode == CHAINS_OPT) settings.Mode = ConversionMode.TakeChainsOnMismatch;
					else if (mode == SITES_OPT) settings.Mode = ConversionMode.TakeSitesOnMismatch;
					else
					{
						Console.WriteLine("Invalid conversion mode \"{0}\"", mode);
						Environment.Exit(255);
					}
				}
				else if (tag.StartsWith(MINCHAINS_PARAM))
				{
					var value = int.Parse(tag.Substring(MINCHAINS_PARAM.Length));
					settings.FilterMinChains = value;
				}
				else if (tag.StartsWith(MAXCHAINS_PARAM))
				{
					var value = int.Parse(tag.Substring(MAXCHAINS_PARAM.Length));
					settings.FilterMaxChains = value;
				}
				else if (tag == "-mf")
				{
					settings.MultipleFiles = true;
				}
				else
				{
					Console.WriteLine("Invalid argument \"{0}\"", tag);
					Environment.Exit(255);
				}
			}
		}

		/// <summary>
		/// Muestra como se usa el programa por la consola
		/// </summary>
		private static void ShowUsage()
		{
			var help =
@"fconvert Converts UniProt XML (xmlns=http://uniprot.org/uniprot rev 1.39) file format to SPMatch XML file format

Usage: 
  fconvert input output [--mode=mflag] [-mf] [--minchains=n] [--maxchains=n]
	
	--mode=mflag   mflag can take one of following.
		skip       -> Skips on mismatch (default)
		chainsonly -> Take info from chain only
		sitesonly  -> Take info from site only
		chains     -> Take info from chain on mismatch
		sites      -> Take info from site on mismatch

	--minchains=n  skip sequences with chain count less than n.
	--maxchains=n  skip sequences with chain count greater than n.
	-mf            Write multiple single files on output path.
";

			Console.WriteLine(help);
		}
	}
}
